{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ba24f599-8993-4dae-96d0-e0dd5ea42d04",
   "metadata": {},
   "source": [
    "# 本节大纲\n",
    "1. 版本介绍，15分钟\n",
    "2. RAG架构增强（Summarize & SearchEngine），30分钟\n",
    "3. API工程化（LangServe & FastAPI），30分钟\n",
    "4. 容器化部署（镜像构建 & 平台部署），30分钟\n",
    "5. 答疑和总结，15分钟"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "605979bf-2d01-40fa-9f86-20133a66f3cc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: openai in /opt/conda/lib/python3.11/site-packages (0.28.1)\n",
      "Requirement already satisfied: pinecone-client in /opt/conda/lib/python3.11/site-packages (2.2.4)\n",
      "Requirement already satisfied: tiktoken in /opt/conda/lib/python3.11/site-packages (0.5.1)\n",
      "Collecting tavily-python\n",
      "  Obtaining dependency information for tavily-python from https://files.pythonhosted.org/packages/aa/12/ea67b0d360d1efffc9c668d403db9ac49fab6b9f1c536840611254577838/tavily_python-0.1.9-py3-none-any.whl.metadata\n",
      "  Downloading tavily_python-0.1.9-py3-none-any.whl.metadata (2.6 kB)\n",
      "Requirement already satisfied: requests>=2.20 in /opt/conda/lib/python3.11/site-packages (from openai) (2.31.0)\n",
      "Requirement already satisfied: tqdm in /opt/conda/lib/python3.11/site-packages (from openai) (4.66.1)\n",
      "Requirement already satisfied: aiohttp in /opt/conda/lib/python3.11/site-packages (from openai) (3.8.6)\n",
      "Requirement already satisfied: pyyaml>=5.4 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (6.0.1)\n",
      "Requirement already satisfied: loguru>=0.5.0 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (0.7.2)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (4.7.1)\n",
      "Requirement already satisfied: dnspython>=2.0.0 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (2.4.2)\n",
      "Requirement already satisfied: python-dateutil>=2.5.3 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (2.8.2)\n",
      "Requirement already satisfied: urllib3>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (2.0.4)\n",
      "Requirement already satisfied: numpy>=1.22.0 in /opt/conda/lib/python3.11/site-packages (from pinecone-client) (1.26.1)\n",
      "Requirement already satisfied: regex>=2022.1.18 in /opt/conda/lib/python3.11/site-packages (from tiktoken) (2023.10.3)\n",
      "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.11/site-packages (from python-dateutil>=2.5.3->pinecone-client) (1.16.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (3.2.0)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (3.4)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests>=2.20->openai) (2023.7.22)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (23.1.0)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (6.0.4)\n",
      "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (4.0.3)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (1.9.2)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (1.4.0)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.11/site-packages (from aiohttp->openai) (1.3.1)\n",
      "Downloading tavily_python-0.1.9-py3-none-any.whl (3.0 kB)\n",
      "Installing collected packages: tavily-python\n",
      "Successfully installed tavily-python-0.1.9\n"
     ]
    }
   ],
   "source": [
    "!pip install openai pinecone-client tiktoken tavily-python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "744b2a4c-5429-452c-993a-8b7c985b206f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "299a5f92-8d15-40b4-94fc-342c05de15f0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "492d3e29-d6fa-4c13-89f2-cd93be365bcf",
   "metadata": {},
   "source": [
    "## 小墨 v0.5 介绍"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8faf6d2f-3525-4e63-84c0-61e69725e230",
   "metadata": {},
   "source": [
    "![v0.5](./resource/images/v0.5.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0e61f128-9ce1-4769-8e92-1dc46e92e774",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1ea87268-69bd-4736-b2d0-b30573f4f138",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99b67efc-9673-4996-b7c9-86026ab71bc7",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49fba5c2-db4a-40d0-9ca9-83fb6bc6cc0c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "64336ec4-9afa-485f-8a06-30277e260883",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在此之前，我们加餐了 环境安装 & 项目部署，所以给这节课腾了不少时间\n",
    "# 用这些时间，我们在来补充下新的技术和知识点"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9c466c1-40d6-4742-abbe-b85dcdde7e44",
   "metadata": {},
   "source": [
    "## RAG 架构增强"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "5295b6b9-b810-4c3b-90b4-6e55c9ea17e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai\n",
    "\n",
    "def ChatCompletion(system_prompt, user_prompt, top_p=1, temperature=0, max_tokens=2048):\n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=\"gpt-3.5-turbo-0613\",\n",
    "        messages=[\n",
    "            {\"role\": \"system\", \"content\": system_prompt},\n",
    "            {\"role\": \"user\", \"content\": user_prompt},\n",
    "        ],\n",
    "        top_p=top_p,\n",
    "        temperature=temperature, \n",
    "        max_tokens=max_tokens,\n",
    "    )\n",
    "    return response[\"choices\"][0][\"message\"][\"content\"]\n",
    "\n",
    "def TextEmbedding(text):\n",
    "    response = openai.Embedding.create(\n",
    "      model=\"text-embedding-ada-002\",\n",
    "      input=[text]\n",
    "    )\n",
    "    return response['data'][0]['embedding']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0ee14499-3001-4697-acce-e264a9eddcc9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pinecone\n",
    "\n",
    "pinecone.init(      \n",
    "\tapi_key='replace to your api key',      \n",
    "\tenvironment='asia-southeast1-gcp-free'      \n",
    ")\n",
    "index = pinecone.Index(\"mobot\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6af56ecc-7ba5-4632-b5c6-59f49fe26260",
   "metadata": {},
   "source": [
    "### 对于理解用户真实问题的缺陷"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "id": "ac96d275-5d79-4031-92e8-5b20669e6321",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 用户的输入可能并不完全是他们想要查找的内容\n",
    "user_prompt = \"你好小墨！我想知道一个问题的答案。可以吗？我是 Carry Yip，是 Google Enterprise 下 Business Solution 负责人。我喜欢大模型和向量数据库。瑶瑶是谁？\"\n",
    "\n",
    "# 使用了错误的问题去做检索\n",
    "result = index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=TextEmbedding(user_prompt)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "f25284ef-0542-4496-a996-619ff2e431b6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "检索: 你好小墨！我想知道一个问题的答案。可以吗？我是 Carry Yip，是 Google Enterprise 下 Business Solution 负责人。我喜欢大模型和向量数据库。瑶瑶是谁？\n",
      "\n",
      "知识库:\n",
      "Answer: 我是小墨，是墨问西东打造的一个智能体。我正在努力翻阅公司相关的知识，希望可以帮到大家解答问题。\n",
      "Question: 你是谁 / 小墨是什么 / 介绍下你自己 \n",
      "Score: 0.845414\n",
      "\n",
      "Answer: 公司的使命是“让创作成为一种生活方式”，他们想为创作者造一个好的创作和变现工具。\n",
      "Question: 墨问西东这家公司主要做什么？\n",
      "Score: 0.816737413\n",
      "\n",
      "Answer: 大模型并不是在所有的生成式场景中都是利器，它有自己的局限，尤其是需要确定结果的场景。当下，我们需要思考，大模型技术，对自己的业务来说，在什么样的场景中，能够大放异彩。\n",
      "Question: 小墨的视角怎么看大模型技术？\n",
      "Score: 0.815748751\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(f'检索: {user_prompt}\\n')\n",
    "print(f'知识库:')\n",
    "knowledge_base = \"\"\n",
    "for item in result['matches']:\n",
    "    knowledge_base += f\"Answer: {item['metadata']['answer']}\\nQuestion: {item['metadata']['question']}\\nScore: {item['score']}\\n\\n\"\n",
    "print(knowledge_base)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "f4d6272d-b244-4e01-9364-7fba58f9ef35",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "系统: 请你根据以下的知识库内容回答用户问题\n",
      "\n",
      "知识库:\n",
      "Answer: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "Question: 瑶瑶是谁\n",
      "Score: 0.983994484\n",
      "\n",
      "Answer: 瑶瑶是墨问西东的全职员工，年方 18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，我也不太清楚了。之前，她和池老师聊过一期播客，你感兴趣可以去听听：\n",
      "https://www.xiaoyuzhoufm.com/episode/632b0aece67030aadb38e231\n",
      "Question:  顾晨瑶 / 瑶瑶是谁\n",
      "Score: 0.914450645\n",
      "\n",
      "Answer: huhu 是墨问西东的运营同事啦。早之前，她在极客时间工作，后来又去了有赞。这次墨问西东创业，她就加入进来负责公司的私域、知识星球、卖桃者说等内容产品。\n",
      "Question: huhu 是谁？\n",
      "Score: 0.861478746\n",
      "\n",
      "\n",
      "用户: 你好小墨！我想知道一个问题的答案。可以吗？我是 Carry Yip，是 Google Enterprise 下 Business Solution 负责人。我喜欢大模型和向量数据库。瑶瑶是谁？\n",
      "用户的真正想问的是:\n",
      "\n",
      "小墨: 瑶瑶是墨问西东的全职员工，年方18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，她和池老师聊过一期播客。\n"
     ]
    }
   ],
   "source": [
    "# 检索出错误的知识，再去回答问题的问题也是错的\n",
    "system_prompt = f\"请你根据以下的知识库内容回答用户问题\\n\\n知识库:\\n{knowledge_base}\"\n",
    "\n",
    "print(f'系统: {system_prompt}')\n",
    "print(f'用户: {user_prompt}\\n')\n",
    "print(f'小墨: {ChatCompletion(system_prompt=system_prompt, user_prompt=user_prompt)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d902e5e1-b20b-416e-92f6-bff1ee665e41",
   "metadata": {},
   "source": [
    "### 推理出真正问题后再去检索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "9fcba0d1-c90f-4fcf-b30e-8013dcfc7686",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户问题: 你好小墨！我想知道一个问题的答案。可以吗？我是 Carry Yip，是 Google Enterprise 下 Business Solution 负责人。我喜欢大模型和向量数据库。瑶瑶是谁？\n",
      "用户的真正想问的是: 瑶瑶是谁？\n"
     ]
    }
   ],
   "source": [
    "system_prompt = f\"请你理解一下用户输入的问题，然后输出用户真正想问的问题，不用解释过程请直接输出\"\n",
    "user_prompt = \"你好小墨！我想知道一个问题的答案。可以吗？我是 Carry Yip，是 Google Enterprise 下 Business Solution 负责人。我喜欢大模型和向量数据库。瑶瑶是谁？\\n用户的真正想问的是:\"\n",
    "\n",
    "real_question = ChatCompletion(system_prompt=system_prompt, user_prompt=user_prompt)\n",
    "print(f'用户问题: {user_prompt} {real_question}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "6f522353-d0c0-4ba7-9b65-600efc941084",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用了真正的用户问题在去做检索和召回\n",
    "result = index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=TextEmbedding(real_question)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "4bfb83f8-93b2-4b00-b3b3-c5e30fd6c6de",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "检索: 瑶瑶是谁？\n",
      "\n",
      "知识库:\n",
      "Answer: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "Question: 瑶瑶是谁\n",
      "Score: 0.983994484\n",
      "\n",
      "Answer: 瑶瑶是墨问西东的全职员工，年方 18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，我也不太清楚了。之前，她和池老师聊过一期播客，你感兴趣可以去听听：\n",
      "https://www.xiaoyuzhoufm.com/episode/632b0aece67030aadb38e231\n",
      "Question:  顾晨瑶 / 瑶瑶是谁\n",
      "Score: 0.914450645\n",
      "\n",
      "Answer: huhu 是墨问西东的运营同事啦。早之前，她在极客时间工作，后来又去了有赞。这次墨问西东创业，她就加入进来负责公司的私域、知识星球、卖桃者说等内容产品。\n",
      "Question: huhu 是谁？\n",
      "Score: 0.861478746\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(f'检索: {real_question}\\n')\n",
    "print(f'知识库:')\n",
    "knowledge_base = \"\"\n",
    "for item in result['matches']:\n",
    "    knowledge_base += f\"Answer: {item['metadata']['answer']}\\nQuestion: {item['metadata']['question']}\\nScore: {item['score']}\\n\\n\"\n",
    "print(knowledge_base)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "c5600225-babf-4fa2-ba46-4b50d2ded144",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "系统: 请你根据以下的知识库内容回答用户问题\n",
      "\n",
      "知识库: Answer: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "Question: 瑶瑶是谁\n",
      "Score: 0.983994484\n",
      "\n",
      "Answer: 瑶瑶是墨问西东的全职员工，年方 18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，我也不太清楚了。之前，她和池老师聊过一期播客，你感兴趣可以去听听：\n",
      "https://www.xiaoyuzhoufm.com/episode/632b0aece67030aadb38e231\n",
      "Question:  顾晨瑶 / 瑶瑶是谁\n",
      "Score: 0.914450645\n",
      "\n",
      "Answer: huhu 是墨问西东的运营同事啦。早之前，她在极客时间工作，后来又去了有赞。这次墨问西东创业，她就加入进来负责公司的私域、知识星球、卖桃者说等内容产品。\n",
      "Question: huhu 是谁？\n",
      "Score: 0.861478746\n",
      "\n",
      "\n",
      "用户: 瑶瑶是谁？\n",
      "\n",
      "小墨: 瑶瑶是墨问西东的全职员工，年方18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，她和池老师聊过一期播客。\n"
     ]
    }
   ],
   "source": [
    "# 检索看起来没有问题了，再去回答下用户问题试试\n",
    "system_prompt = f\"请你根据以下的知识库内容回答用户问题\\n\\n知识库:\\n{knowledge_base}\"\n",
    "\n",
    "print(f'系统: {system_prompt}')\n",
    "print(f'用户: {real_question}\\n')\n",
    "print(f'小墨: {ChatCompletion(system_prompt=system_prompt, user_prompt=real_question)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "id": "2ba679c5-fd91-4b66-ac42-af6722f7921b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "系统: 请你根据以下的知识库内容回答用户问题\n",
      "\n",
      "知识库: Answer: 瑶瑶是墨问西东的颜值担当，遥遥领先。\n",
      "Question: 瑶瑶是谁\n",
      "Score: 0.983994484\n",
      "\n",
      "Answer: 瑶瑶是墨问西东的全职员工，年方 18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，我也不太清楚了。之前，她和池老师聊过一期播客，你感兴趣可以去听听：\n",
      "https://www.xiaoyuzhoufm.com/episode/632b0aece67030aadb38e231\n",
      "Question:  顾晨瑶 / 瑶瑶是谁\n",
      "Score: 0.914450645\n",
      "\n",
      "Answer: huhu 是墨问西东的运营同事啦。早之前，她在极客时间工作，后来又去了有赞。这次墨问西东创业，她就加入进来负责公司的私域、知识星球、卖桃者说等内容产品。\n",
      "Question: huhu 是谁？\n",
      "Score: 0.861478746\n",
      "\n",
      "\n",
      "用户: 你好小墨！我想知道一个问题的答案。可以吗？我是 Carry Yip，是 Google Enterprise 下 Business Solution 负责人。我喜欢大模型和向量数据库。瑶瑶是谁？\n",
      "用户的真正想问的是:\n",
      "\n",
      "小墨: 瑶瑶是墨问西东的全职员工，年方18，肤白貌美。加入墨问西东之前，她负责极客时间的训练营业务。再之前，她和池老师聊过一期播客，你感兴趣可以去听听：\n",
      "https://www.xiaoyuzhoufm.com/episode/632b0aece67030aadb38e231\n"
     ]
    }
   ],
   "source": [
    "# 如果召回准确，LLM的推理能力也可以理解到问题\n",
    "system_prompt = f\"请你根据以下的知识库内容回答用户问题\\n\\n知识库: {knowledge_base}\"\n",
    "\n",
    "print(f'系统: {system_prompt}')\n",
    "print(f'用户: {user_prompt}\\n')\n",
    "print(f'小墨: {ChatCompletion(system_prompt=system_prompt, user_prompt=user_prompt)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4118c64f-1c03-43d6-ac2d-51359793ca1e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 目前阶段 小墨的知识来源 \n",
    "# 1. 大语言模型训练阶段的数据\n",
    "# 2. 我们手动维护知识库的数据\n",
    "\n",
    "# 我们要改变小墨的知识？\n",
    "# 1. 重新微调大语言模型，但是始终时效都更不上，成本比较高\n",
    "# 2. 不停的去维护知识库，但是边界总得要有，要不然就是一个百度百科了\n",
    "\n",
    "# 还有其他方式吗？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e51c17c5-78ef-4da2-97c1-f40dd317865d",
   "metadata": {},
   "source": [
    "### 对于实时性问题的缺陷"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "id": "d49200b9-ad64-47cc-93b5-1517af2c8eef",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 试试如果是具有实时性的任务\n",
    "user_prompt = \"瑶瑶很喜欢民谣，而她最喜欢的歌手赵雷在前几天也发布了新歌，那个歌名和专辑叫什么来着？\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "id": "5ced917d-a497-4a2a-a321-27d15fbe4eea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "用户问题: 瑶瑶很喜欢民谣，而她最喜欢的歌手赵雷最近也发布了专辑，最新的专辑叫什么来着？\n",
      "用户的真正问题是: 赵雷最新的专辑叫什么？\n"
     ]
    }
   ],
   "source": [
    "# 推理出真正的用户问题\n",
    "system_prompt = f\"请你理解一下用户输入的问题，然后输出用户真正想问的问题，不用解释过程请直接输出\"\n",
    "user_prompt = \"瑶瑶很喜欢民谣，而她最喜欢的歌手赵雷最近也发布了专辑，最新的专辑叫什么来着？\\n用户的真正问题是:\"\n",
    "\n",
    "real_question = ChatCompletion(system_prompt=system_prompt, user_prompt=user_prompt)\n",
    "print(f'用户问题: {user_prompt} {real_question}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "id": "3ca2f7ed-b005-4960-8aa9-a845c46845ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 试试对知识库的内容检索\n",
    "result = index.query(\n",
    "    top_k=3,\n",
    "    include_values=False,\n",
    "    include_metadata=True,\n",
    "    vector=TextEmbedding(real_question)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "id": "99d1e628-06f8-4871-9adb-b726ebe18acb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "检索: 赵雷最新的专辑叫什么？\n",
      "\n",
      "知识库:\n",
      "Answer: 五年前池老师应邀加入了极客邦科技，与公司的合伙人团队（霍太稳、Selina、Gary）一起了打造极客时间这个产品，2017 年 10 月，极客时间 App 正式上线，后陆续构建极客时间训练营和企业版、InfoQ 写作平台等业务产品，帮助公司完成从媒体公司到集 IT 媒体、数字化人才学习和企业培训的综合性学习平台的战略转型。\n",
      "Question: 说说池老师和极客时间的故事？\n",
      "Score: 0.806622148\n",
      "\n",
      "Answer: 微信小程序搜索墨问便签。墨问便签并不是传统意义上的笔记软件，它是一个创作和分享工具，以小程序为载体，让有价值的内容，在人与人之间流动。\n",
      "Question: 墨问西东有什么产品？\n",
      "Score: 0.805880606\n",
      "\n",
      "Answer: 公司的使命是“让创作成为一种生活方式”，他们想为创作者造一个好的创作和变现工具。\n",
      "Question: 墨问西东这家公司主要做什么？\n",
      "Score: 0.803754628\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 可以发现，答案完全是错的（知识库没有覆盖的场景）\n",
    "print(f'检索: {real_question}\\n')\n",
    "print(f'知识库:')\n",
    "knowledge_base = \"\"\n",
    "for item in result['matches']:\n",
    "    knowledge_base += f\"Answer: {item['metadata']['answer']}\\nQuestion: {item['metadata']['question']}\\nScore: {item['score']}\\n\\n\"\n",
    "print(knowledge_base)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "a3880013-9e41-4b95-868b-b09d1103cf5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "系统: 请你根据以下的知识库内容回答用户问题\n",
      "\n",
      "知识库:\n",
      "Answer: 五年前池老师应邀加入了极客邦科技，与公司的合伙人团队（霍太稳、Selina、Gary）一起了打造极客时间这个产品，2017 年 10 月，极客时间 App 正式上线，后陆续构建极客时间训练营和企业版、InfoQ 写作平台等业务产品，帮助公司完成从媒体公司到集 IT 媒体、数字化人才学习和企业培训的综合性学习平台的战略转型。\n",
      "Question: 说说池老师和极客时间的故事？\n",
      "Score: 0.806622148\n",
      "\n",
      "Answer: 微信小程序搜索墨问便签。墨问便签并不是传统意义上的笔记软件，它是一个创作和分享工具，以小程序为载体，让有价值的内容，在人与人之间流动。\n",
      "Question: 墨问西东有什么产品？\n",
      "Score: 0.805880606\n",
      "\n",
      "Answer: 公司的使命是“让创作成为一种生活方式”，他们想为创作者造一个好的创作和变现工具。\n",
      "Question: 墨问西东这家公司主要做什么？\n",
      "Score: 0.803754628\n",
      "\n",
      "\n",
      "用户: 赵雷最新的专辑叫什么？\n",
      "\n",
      "小墨: 很抱歉，我无法回答你关于赵雷最新专辑的问题。我的知识库中没有关于赵雷的信息。建议你通过其他渠道获取最新的专辑信息。\n"
     ]
    }
   ],
   "source": [
    "# 联合大语言模型回答，也是错的\n",
    "system_prompt = f\"请你根据以下的知识库内容回答用户问题\\n\\n知识库:\\n{knowledge_base}\"\n",
    "\n",
    "print(f'系统: {system_prompt}')\n",
    "print(f'用户: {real_question}\\n')\n",
    "print(f'小墨: {ChatCompletion(system_prompt=system_prompt, user_prompt=real_question)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "id": "9b4b903f-2a69-486f-869f-35b2c7adb3b1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "系统: \n",
      "用户: 赵雷最新的专辑叫什么？\n",
      "\n",
      "小墨: 赵雷最新的专辑叫做《无法长大》。\n"
     ]
    }
   ],
   "source": [
    "# 不联合知识库，直接用大语言模型来回答呢？\n",
    "system_prompt = \"\"\n",
    "\n",
    "print(f'系统: {system_prompt}')\n",
    "print(f'用户: {real_question}\\n')\n",
    "print(f'小墨: {ChatCompletion(system_prompt=system_prompt, user_prompt=real_question)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50fa73ec-11a2-4024-a663-5d098346e883",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 不错，可以回答出来，但是这个专辑，不是最近发布的... \n",
    "\n",
    "# 所以大语言模型也是对于时效性任务无法胜任的 (大语言模型的先验知识，截止到训练时的数据，例如 GPT-3 是 2021.09)\n",
    "\n",
    "# 那该怎么办？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4de63ab4-c38d-4ada-93dd-bc7fe460205f",
   "metadata": {},
   "source": [
    "### 加入搜素引擎获取最新的动态"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "id": "1c1cac6b-0d1f-406f-ae6e-199dcd4f2888",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 搜索引擎登场，大部分的消息、新闻都是可以通过搜索引擎进行实时的获取\n",
    "# https://app.tavily.com/sign-in\n",
    "\n",
    "from tavily import Client\n",
    "tavily = Client(api_key=\"replace to your api key\")\n",
    "results = tavily.search(query=real_question, max_results=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "id": "971206e8-f16f-47ed-ba1c-7441c0be70d2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 156,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(results.get('results'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "id": "7708636e-0be4-45eb-9b17-f850351f30ee",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'query': '赵雷最新的专辑叫什么？',\n",
       " 'follow_up_questions': None,\n",
       " 'response_time': 2.08,\n",
       " 'answer': None,\n",
       " 'images': None,\n",
       " 'results': [{'title': '\\u200e赵雷 - Apple Music',\n",
       "   'url': 'https://music.apple.com/cn/artist/赵雷/937112027',\n",
       "   'content': '赵雷 最新发布 2022年8月29日 署前街少年 10 首歌曲 歌曲排行 我记得 署前街少年 · 2022年 成都 成都 - Single · 2016年 鼓楼 无法长大 · 2016年 南方姑娘 赵小雷 · 2011年 成都 无法长大 · 2016年 画 赵小雷 · 2011年 理想 吉姆餐厅 · 2014年 阿刁 无法长大 · 2016年 我们的时光 吉姆餐厅 · 2014年 三十岁的女人 吉姆餐厅 · 2014年 专辑 署前街少年 2022年 无法长大 2016年 吉姆餐厅 2014年 赵小雷 2011年 艺人歌单 赵雷代表作',\n",
       "   'score': 0.9608,\n",
       "   'raw_content': None},\n",
       "  {'title': '如何评价赵雷的新专辑《署前街少年》？ - 知乎',\n",
       "   'url': 'https://www.zhihu.com/question/549694544',\n",
       "   'content': '赵雷上一次发专辑还是2016年的《无法长大》，这张专辑中有那首让雷子爆红成为顶流民谣歌手的《成都》，只要赵雷想，这首歌已足够他吃一辈子了，可他没有这么做。 看得出来，他仍然想用音乐去表达不同的东西，想让听众想起赵雷时除了《成都》还能够想起更多的作品，于是，他用了足足6年的时间沉淀、思考，才交出自己的第4张作品。 这张专辑里的10首歌每首都有各自的特点，接下来咱们就逐一分析。 （因版权问题所以没有音频） 一、《 阿卜杜拉 》 【关键词】：主歌call and response；副歌多利亚调式 开头以场景采样音效作为引子，随后接复古感的小号，把人拉进庄严肃穆又带有暗黄色调的场景中。',\n",
       "   'score': 0.95843,\n",
       "   'raw_content': None},\n",
       "  {'title': '署前街少年（2022年赵雷发行的音乐专辑）_百度百科',\n",
       "   'url': 'https://baike.baidu.com/item/署前街少年/61920127',\n",
       "   'content': '《署前街少年》是 赵雷 于2022年8月29日发行的个人第四张音乐专辑，共收录10首歌曲，由赵雷担任制作人 [1] 。 2023年7月1日，赵雷凭借该专辑提名 第34届台湾金曲奖 最佳华语男歌手奖 [4] 。 8月24日，该专辑获得 第1届浪潮音乐大赏 最佳民谣专辑奖 [3] 。 中文名 署前街少年 外文名 Teen on Shuqian Street 专辑语言 普通话 专辑歌手 赵雷 曲目数量 10 首 音乐风格 民谣 唱片公司 StreetVoice/上海九平指文化工作室 发行日期 2022年8月29日 发行地区 中国 制作人 赵雷 目录 1 创作背景 2 专辑曲目 3 专辑鉴赏 4 获奖记录 创作背景 播报',\n",
       "   'score': 0.93538,\n",
       "   'raw_content': None},\n",
       "  {'title': '赵雷 - 维基百科，自由的百科全书',\n",
       "   'url': 'https://zh.wikipedia.org/wiki/赵雷',\n",
       "   'content': '赵雷（1986年7月20日 — ），中国大陆民谣歌手，獨立音樂人，唱作人，出生于北京，民谣圈内称他雷子。 早期曾有过酒吧歌手和流浪歌手的经历，去过西藏，丽江等地，也参加过一些综艺节目，办过一些小型巡演，2017年因参加湖南卫视《歌手2017》而走红，目前已发行了4张錄音室專輯。',\n",
       "   'score': 0.91261,\n",
       "   'raw_content': None},\n",
       "  {'title': '署前街少年 - 赵雷（雷子） - 专辑 - 网易云音乐',\n",
       "   'url': 'https://music.163.com/album?id=150127127',\n",
       "   'content': '歌手： 赵雷 发行时间： 2022-08-29 发行公司： StreetVoice/上海九平指文化工作室 播放 收藏 (32993) 下载 ( 6747) 专辑介绍： 我是渠边偷偷抽烟枪已上了膛的少年 我要代表恐惧和这世界的阴暗谈一谈 两面都是高墙只有一条路能穿过黑暗 可我没有金钱也没有得到金钱的答案 他妈坐在红灯区里对经过的男人挤眼 他却笑话我父亲是身上沾满泥的商贩 一块石头也可以从刀子那里要回尊严 我是脸上沾满血却不需要安慰的少年 只有离开才能改写这命运 我才不是无药可救的少... 展开 生成外链播放器 包含歌曲列表 10首歌 加载中...',\n",
       "   'score': 0.90873,\n",
       "   'raw_content': None}]}"
      ]
     },
     "execution_count": 157,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "id": "9664a155-7c62-4b85-a1d5-346c0a1c9d8e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "title: ‎赵雷 - Apple Music\n",
      "content: 赵雷 最新发布 2022年8月29日 署前街少年 10 首歌曲 歌曲排行 我记得 署前街少年 · 2022年 成都 成都 - Single · 2016年 鼓楼 无法长大 · 2016年 南方姑娘 赵小雷 · 2011年 成都 无法长大 · 2016年 画 赵小雷 · 2011年 理想 吉姆餐厅 · 2014年 阿刁 无法长大 · 2016年 我们的时光 吉姆餐厅 · 2014年 三十岁的女人 吉姆餐厅 · 2014年 专辑 署前街少年 2022年 无法长大 2016年 吉姆餐厅 2014年 赵小雷 2011年 艺人歌单 赵雷代表作\n",
      "score: 0.9608\n",
      "\n",
      "title: 如何评价赵雷的新专辑《署前街少年》？ - 知乎\n",
      "content: 赵雷上一次发专辑还是2016年的《无法长大》，这张专辑中有那首让雷子爆红成为顶流民谣歌手的《成都》，只要赵雷想，这首歌已足够他吃一辈子了，可他没有这么做。 看得出来，他仍然想用音乐去表达不同的东西，想让听众想起赵雷时除了《成都》还能够想起更多的作品，于是，他用了足足6年的时间沉淀、思考，才交出自己的第4张作品。 这张专辑里的10首歌每首都有各自的特点，接下来咱们就逐一分析。 （因版权问题所以没有音频） 一、《 阿卜杜拉 》 【关键词】：主歌call and response；副歌多利亚调式 开头以场景采样音效作为引子，随后接复古感的小号，把人拉进庄严肃穆又带有暗黄色调的场景中。\n",
      "score: 0.95843\n",
      "\n",
      "title: 署前街少年（2022年赵雷发行的音乐专辑）_百度百科\n",
      "content: 《署前街少年》是 赵雷 于2022年8月29日发行的个人第四张音乐专辑，共收录10首歌曲，由赵雷担任制作人 [1] 。 2023年7月1日，赵雷凭借该专辑提名 第34届台湾金曲奖 最佳华语男歌手奖 [4] 。 8月24日，该专辑获得 第1届浪潮音乐大赏 最佳民谣专辑奖 [3] 。 中文名 署前街少年 外文名 Teen on Shuqian Street 专辑语言 普通话 专辑歌手 赵雷 曲目数量 10 首 音乐风格 民谣 唱片公司 StreetVoice/上海九平指文化工作室 发行日期 2022年8月29日 发行地区 中国 制作人 赵雷 目录 1 创作背景 2 专辑曲目 3 专辑鉴赏 4 获奖记录 创作背景 播报\n",
      "score: 0.93538\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 和向量数据库一样的方式，提取得分最高的 top-k 个结果\n",
    "# 也可以对 score 进行抑制比较低的得分\n",
    "search_result = \"\"\n",
    "for i, item in enumerate(results.get('results')):\n",
    "    if i == 3:\n",
    "        break\n",
    "    search_result += f\"title: {item['title']}\\ncontent: {item['content']}\\nscore: {item['score']}\\n\\n\"\n",
    "print(search_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "id": "3e1fa15b-e1da-4b7d-b6f6-488ffc54fc86",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "系统: 请你根据以下的搜索引擎结果回答用户问题\n",
      "\n",
      "搜索引擎结果:\n",
      "title: ‎赵雷 - Apple Music\n",
      "content: 赵雷 最新发布 2022年8月29日 署前街少年 10 首歌曲 歌曲排行 我记得 署前街少年 · 2022年 成都 成都 - Single · 2016年 鼓楼 无法长大 · 2016年 南方姑娘 赵小雷 · 2011年 成都 无法长大 · 2016年 画 赵小雷 · 2011年 理想 吉姆餐厅 · 2014年 阿刁 无法长大 · 2016年 我们的时光 吉姆餐厅 · 2014年 三十岁的女人 吉姆餐厅 · 2014年 专辑 署前街少年 2022年 无法长大 2016年 吉姆餐厅 2014年 赵小雷 2011年 艺人歌单 赵雷代表作\n",
      "score: 0.9608\n",
      "\n",
      "title: 如何评价赵雷的新专辑《署前街少年》？ - 知乎\n",
      "content: 赵雷上一次发专辑还是2016年的《无法长大》，这张专辑中有那首让雷子爆红成为顶流民谣歌手的《成都》，只要赵雷想，这首歌已足够他吃一辈子了，可他没有这么做。 看得出来，他仍然想用音乐去表达不同的东西，想让听众想起赵雷时除了《成都》还能够想起更多的作品，于是，他用了足足6年的时间沉淀、思考，才交出自己的第4张作品。 这张专辑里的10首歌每首都有各自的特点，接下来咱们就逐一分析。 （因版权问题所以没有音频） 一、《 阿卜杜拉 》 【关键词】：主歌call and response；副歌多利亚调式 开头以场景采样音效作为引子，随后接复古感的小号，把人拉进庄严肃穆又带有暗黄色调的场景中。\n",
      "score: 0.95843\n",
      "\n",
      "title: 署前街少年（2022年赵雷发行的音乐专辑）_百度百科\n",
      "content: 《署前街少年》是 赵雷 于2022年8月29日发行的个人第四张音乐专辑，共收录10首歌曲，由赵雷担任制作人 [1] 。 2023年7月1日，赵雷凭借该专辑提名 第34届台湾金曲奖 最佳华语男歌手奖 [4] 。 8月24日，该专辑获得 第1届浪潮音乐大赏 最佳民谣专辑奖 [3] 。 中文名 署前街少年 外文名 Teen on Shuqian Street 专辑语言 普通话 专辑歌手 赵雷 曲目数量 10 首 音乐风格 民谣 唱片公司 StreetVoice/上海九平指文化工作室 发行日期 2022年8月29日 发行地区 中国 制作人 赵雷 目录 1 创作背景 2 专辑曲目 3 专辑鉴赏 4 获奖记录 创作背景 播报\n",
      "score: 0.93538\n",
      "\n",
      "\n",
      "用户: 赵雷最新的专辑叫什么？\n",
      "\n",
      "小墨: 赵雷最新的专辑叫《署前街少年》。\n"
     ]
    }
   ],
   "source": [
    "# 有了搜索引擎的结果，再交给大语言模型试试\n",
    "system_prompt = f\"请你根据以下的搜索引擎结果回答用户问题\\n\\n搜索引擎结果:\\n{search_result}\"\n",
    "\n",
    "print(f'系统: {system_prompt}')\n",
    "print(f'用户: {real_question}\\n')\n",
    "print(f'小墨: {ChatCompletion(system_prompt=system_prompt, user_prompt=real_question)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ada4242-b9e6-4b78-9014-ee0e3018b6a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 但是有个小插曲，赵雷前几天悄悄了又发专辑《欠父亲的话》，\n",
    "# 可能是没有什么曝光，也可能是只有一首歌，所以结果在搜索引擎上排名也靠不了前"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38612c9e-6d43-498a-a956-52ada863c6e8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b01bdcc-231d-43a8-a531-b52677e22708",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "49aad1e4-9b14-49bf-97c5-e519dc734d3e",
   "metadata": {},
   "source": [
    "## API 工程化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 208,
   "id": "c2ad5230-ed8a-4a6a-b78e-f7cb1e7066c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 上代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46387564-e362-40d5-ba1b-45287c1c295d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "20c62fc9-ae17-4af2-b53a-35bb5ac14d73",
   "metadata": {},
   "source": [
    "### LangServe "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 210,
   "id": "9498b929-ad0d-47f6-b462-cfa7132b0a60",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在前一周 LangChain 才更新的技术，\n",
    "# 我们做一个吃螃蟹的，安排！\n",
    "# 大大提高的服务暴露能力，将 Chain 变成 API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "390028dc-ce78-4483-a6c7-64e3159d549e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09ec8190-8a0c-46f4-ae2d-71d89c1fa68e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f94a60a6-f8c0-4475-a22b-56eb1b0da840",
   "metadata": {},
   "source": [
    "## 容器化部署"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99e8a580-080b-4364-b59f-2d021e4a1216",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 容器化为了什么？\n",
    "\n",
    "# 部署、分发"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5dd7075-21ac-425b-b9a3-9d2973cea555",
   "metadata": {},
   "source": [
    "![Containerization](./resource/images/Containerization.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d61fa63e-f472-4cac-a98a-15030320df1f",
   "metadata": {},
   "source": [
    "### 打包镜像容器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "775e3eaf-f8f7-4334-94a0-074532235493",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 如果有细心的同学，会发现其实每一个版本的工程代码中\n",
    "# 都有一个叫 Dockerfile 的文件， 这实际就是我们完成容器镜像打包的必需品\n",
    "# ./v0.5/Dockerfile"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5bf20c31-7fd1-47cd-89b0-e8732b1bcd6b",
   "metadata": {},
   "source": [
    "```\n",
    "# 基础镜像\n",
    "FROM python:3.10-slim\n",
    "\n",
    "# 维护者信息\n",
    "MAINTAINER <Carry Yip> carryyip1996@gmail.com\n",
    "\n",
    "# 工作目录\n",
    "WORKDIR /app\n",
    "\n",
    "# 复制本地的文件到镜像中\n",
    "COPY . .\n",
    "\n",
    "# 安装依赖\n",
    "RUN pip install -r requirements.txt -i https://pypi.mirrors.ustc.edu.cn/simple/\n",
    "\n",
    "# 声明暴露端口\n",
    "EXPOSE 7860\n",
    "\n",
    "# 启动时候运行的命令\n",
    "CMD [\"python\", \"web.py\"]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2fe6d78a-0353-4e2e-986d-43621029d9d7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 打包时，只需要一句命令就可以\n",
    "# docker build -t carryyip/mobot:v0.5 ."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b223ba8-8a47-4fab-a276-187d03816af6",
   "metadata": {},
   "source": [
    "### 推上容器仓库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2c9ebdce-1276-4ff1-8d95-f868991cf65c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 便于其他机器访问，例如CI/CD的系统中，CI负责打包，CD负责部署\n",
    "# docker push carryyip/mobot:v0.5 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0c3a1ff-9031-4d21-b54c-dd5a5ce344e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 或者像我们上课一样，在仓库中把镜像拉到本地就可以跑了\n",
    "# docker pull carryyip/mobot:v0.5 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18920d39-9bd1-40e6-9dfa-06cfd56ff606",
   "metadata": {},
   "source": [
    "### 本地把容器跑起来"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11a2eff5-102f-4eef-9ae0-11d5512ade04",
   "metadata": {},
   "outputs": [],
   "source": [
    "# docker run -it --name mobot-v5 -p 7860:7860 --rm carryyip/mobot:v0.5 /bin/bash"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88a977f7-7d51-46ea-840e-883b2409edf3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d476725a-3697-41ca-9ae3-41e5494fa6e3",
   "metadata": {},
   "source": [
    "### 生产上并不会单机跑，而是集群跑"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "603f63bf-5602-4139-9c5a-1a0550dc10ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Kubernetes 容器平台\n",
    "# 为什么还需要集群？\n",
    "# 或者说是为什么需要 Kubernetes \n",
    "\n",
    "# 如果服务挂掉了，能不能故障自愈..\n",
    "# 如果是需要扩容100个副本，能不能马上就扩容到..\n",
    "# 如果是需要快速发布，能不能做到..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7dd10def-ae4f-4747-ad61-74495b2ddd59",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 参考 ./deploy/ 文件夹中的各个文件\n",
    "\n",
    "# 工作负载相关，可以理解成负责创建应用的组件\n",
    "# deployment.yaml\n",
    "\n",
    "# 服务暴露相关，给集群内的其他服务进行访问\n",
    "# service.yaml\n",
    "\n",
    "# 服务暴露相关，给集群外的最终用户访问\n",
    "# ingress.yaml\n",
    "\n",
    "# 配置文件相关，只是用资源对象做了封装\n",
    "# configmap.yaml"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a814e1f-eb2e-45ce-b716-4ef220a52e57",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 部署应用\n",
    "# kubectl apply -f ./deploy/\n",
    "\n",
    "# 删除应用\n",
    "# kubectl delete -f ./deploy/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0440b005-f956-46a7-a359-435ca7370250",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "76261f7a-a415-4e41-a799-a599f2726906",
   "metadata": {},
   "source": [
    "## 总结和回顾"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aed608d1-b22b-4250-9686-6dbdbb4ff5cb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "65376480-779f-440f-80b3-184e1ec4329c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d0f07ea-9eff-4750-9b50-72588f8c9229",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
